package cn.edu.zjut.mina.handler;

import java.sql.Date;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import cn.edu.zjut.mina.bean.RoomInfo;
import cn.edu.zjut.mina.bean.StandardFormat;
import cn.edu.zjut.mina.bean.UserSession;
import cn.edu.zjut.mina.interf.IRoomInfo;
import cn.edu.zjut.mina.po.UserInfo;
import cn.edu.zjut.mina.protocal.JMessageProtocalReq;
import cn.edu.zjut.mina.protocal.JMessageProtocalRes;
import cn.edu.zjut.mina.protocal.ProtocalRegulation;
import cn.edu.zjut.mina.repository.UserInfoRepository;
import cn.edu.zjut.mina.service.IBackToHallService;
import cn.edu.zjut.mina.service.IBackToRoomService;
import cn.edu.zjut.mina.service.IGameOverService;
import cn.edu.zjut.mina.service.IIPService;
import cn.edu.zjut.mina.service.IMessageService;
import cn.edu.zjut.mina.service.INotificationService;
import cn.edu.zjut.mina.service.IQuitRoomService;
import cn.edu.zjut.mina.service.IRoomCardService;
import cn.edu.zjut.mina.service.IUserCreateRoomService;
import cn.edu.zjut.mina.service.IUserFindRoomService;
import cn.edu.zjut.mina.service.IUserInitService;
import cn.edu.zjut.mina.service.IUserPrepareService;
import cn.edu.zjut.mina.service.IUserShowCardsService;
import cn.edu.zjut.mina.util.DateUtils;
import cn.edu.zjut.mina.util.GsonUtils;
import cn.edu.zjut.mina.util.UserMap;
import cn.edu.zjut.mina.util.UserSessionMap;
import cn.edu.zjut.mina.xcmahjong.XcmjService;
import halma.Test;

public class MinaHandler extends IoHandlerAdapter {

	private final static Log log = LogFactory.getLog(MinaHandler.class);
	/**
	 * 用于存放用户信息的集合
	 */
	private final UserSessionMap userSessionMap = UserSessionMap.getInstance();
	@Autowired
	private UserInfoRepository userInfoRepository;
	/**
	 * 用于存放用户信息的集合
	 */
	private final UserMap userMap = UserMap.getInstance();

	@Qualifier("userCreateRoomService")
	@Autowired
	private IUserCreateRoomService userCreateRoomService;

	@Qualifier("userFindRoomService")
	@Autowired
	private IUserFindRoomService userFindRoomService;

	@Qualifier("userPrepareService")
	@Autowired
	private IUserPrepareService userPrepareService;

	@Qualifier("userShowCardsService")
	@Autowired
	private IUserShowCardsService userShowCardsService;

	@Qualifier("userInitService")
	@Autowired
	private IUserInitService userInitService;

	@Qualifier("gameOverService")
	@Autowired
	private IGameOverService gameOverService;

	@Qualifier("messageService")
	@Autowired
	private IMessageService messageService;

	@Qualifier("iPService")
	@Autowired
	private IIPService iPService;

	@Qualifier("roomCardService")
	@Autowired
	private IRoomCardService roomCardService;

	@Qualifier("quitRoomService")
	@Autowired
	private IQuitRoomService quitRoomService;

	@Qualifier("backToHallService")
	@Autowired
	private IBackToHallService backToHallService;

	@Qualifier("backToRoomService")
	@Autowired
	private IBackToRoomService backToRoomService;

	@Qualifier("notificationService")
	@Autowired
	private INotificationService notificationService;

	public MinaHandler() {
		// TODO Auto-generated constructor stub
	}

	@Override
	public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
		log.error(String.format("Server产生异常!"));
	}

	@Override
	public void messageReceived(IoSession session, Object message) throws Exception {
		System.out.println("来自Client[%s]的消息:%s" + session.getRemoteAddress() + message.toString());

		/**
		 * 接收信息
		 */
		StandardFormat inJson = GsonUtils.jsonToBean(((JMessageProtocalReq) message).getContent(),
				StandardFormat.class);

		// 函数操作
		short functionCode = ((JMessageProtocalReq) message).getFunctionCode();
		System.out.println(DateUtils.getTime() + "functionCode = " + functionCode + "服务器收到消息:" + message.toString());
		JMessageProtocalRes res;

		if (inJson.userId != null) {
			session.setAttribute("userid", inJson.userId);
			System.out.println("userid=" + inJson.userId);
			if (userInfoRepository == null)
				System.out.println("userInfoRepository用户查找为空");
			if (userInfoRepository.findByUserId(inJson.userId) == null)
				System.out.println("用户查找为空");
			UserInfo user = userInfoRepository.findByUserId(inJson.userId);
			session.setAttribute("user", user.getNickName() + inJson.userId);
		}

		switch (functionCode) {
		case FUNCTIONCODE_RECONNECT:// 用户登入后的初始查询，用于数据恢复和获取用户信息
			res = userInitService.init(inJson, session);
			if (res != null)
				session.write(res);
			break;
		case FUNCTIONCODE_CREATEROOM:// 创建房间
			// userCreateRoomService = new UserCreateRoomServiceImpl();
			res = userCreateRoomService.createRoom(inJson, session);
			session.write(res);
			break;
		case FUNCTIONCODE_JOINROOM:// 加入房间
			// userFindRoomService = new UserFindRoomServiceImpl();
			res = userFindRoomService.findRoom(inJson, session);
			if (res != null)
				session.write(res);
			break;
		case FUNCTIONCODE_READY:// 准备
			// userPrepareService = new UserPrepareServiceImpl();
			res = userPrepareService.prepare(inJson, session);
			if (res != null)
				session.write(res);
			break;
		case FUNCTIONCODE_SHOWCARD:// 亮牌
			// userShowCardsService = new UserShowCardsServiceImpl();
			res = userShowCardsService.showCards(inJson, session);
			if (res != null)
				session.write(res);
			break;
		case FUNCTIONCODE_SENDMESSAGE:// 发送消息
			res = messageService.sendMessage(inJson, session);
			if (res != null)
				session.write(res);
			break;
		case FUNCTIONCOD_APPLYDIS:// 提交退房，暂时没用
			res = quitRoomService.quitRoom(inJson, session);
			if (res != null)
				session.write(res);
			break;
		case 23:// 退房申请，暂时没用
			res = quitRoomService.applyQuitRoom(inJson, session);
			if (res != null)
				session.write(res);
			break;
		case FUNCTIONCOD_GETIP:// 获取IP地址
			res = iPService.getIp(inJson, session);
			if (res != null)
				session.write(res);
			break;
		case FUNCTIONCOD_RETURNTOHALL:// 返回大厅
			res = backToHallService.backToHall(inJson, session);
			if (res != null)
				session.write(res);
			break;
		case FUNCTIONCOD_RETURNTOROOM:// 返回游戏房间
			res = backToRoomService.backToRoom(inJson, session);
			if (res != null)
				session.write(res);
			break;
		case FUNCTIONCOD_DISROOM:// 房主一键解散房间
			res = quitRoomService.constraintQuitRoom(inJson, session);
			if (res != null)
				session.write(res);
			break;
		case FUNCTIONCOD_RECONNECTINGAME:// 游戏中断线重连
			res = userInitService.init(inJson, session);
			if (res != null)
				session.write(res);
			break;
		case FUNCTIONCOD_GETROOMCARD:// 请求房卡数
			res = roomCardService.getRoomCard(inJson, session);
			if (res != null)
				session.write(res);

		case FUNCTIONCOD_HU_XCMJ:
			XcmjService.doHu(inJson, session);
			break;
		case FUNCTIONCOD_ZIMOMINGGANG_XCMJ: // 自摸明杠
			XcmjService.doZimoMingGang(inJson, session);
			break;
		case FUNCTIONCOD_ZIMOANGANG_XCMJ: // 自摸暗杠
			XcmjService.doZimoAnGang(inJson, session);
			break;
		case FUNCTIONCOD_DISCARD_XCMJ:
			XcmjService.disCard(inJson, session);
			break;
		case FUNCTIONCOD_HGPQUEUE_XCMJ:
			XcmjService.hpgQueue(inJson, session);
			break;
		case FUNCTIONCOD_PASS_XCMJ:
			XcmjService.doPass(inJson, session);
			break;

		case 901:// 游戏初始化
			Test.start(inJson, session);
			break;
		case 902:// 获取ai步骤
			Test.move(inJson, session);
			break;
		case 903:// 获取ai步骤
			Test.ai(inJson, session);
			break;
		default:
			break;
		}

		// //获取客户端发过来的key
		// String key = message.toString();
		// System.out.println("message :"+message.toString());
		// String carPark_id = key.substring(key.indexOf("=") + 1);
		// System.out.println("carPark_id :"+carPark_id);
		//
		// //保存客户端的会话session
		// SessionMap sessionMap = SessionMap.newInstance();
		// sessionMap.addSession(carPark_id, session);
		// //session.write("qqqqqqqqqqqqqqqqqqqq\r\n");
		// myService.MethodOne(carPark_id);

	}

	@Override
	public void messageSent(IoSession session, Object message) throws Exception {
		System.out.println(DateUtils.getTime() + "向用户" + session.getAttribute("user") + "发送消息" + message.toString());
	}

	@Override
	public void sessionClosed(IoSession session) throws Exception {

		System.out.println(DateUtils.getTime() + "用户" + session.getAttribute("user") + "的会话关闭");

		String userId = (String) session.getAttribute("userid");

		UserInfo userInfo = userMap.get(userId).user;
		String roomId = userInfo.getRoomId();

		// 以下判断session是否被替换，以此来判断是否需要将这个玩家的准备状态取消，再设置离线状态
		if (roomId != null) {
			IRoomInfo roomInfo = userSessionMap.get(roomId);
			List<UserSession> userSessions = roomInfo.getUserSessions();
			System.out.println("userSessions.size():" + userSessions.size());
			for (int i = 0; i < userSessions.size(); i++) {
				UserSession uSession = userSessions.get(i);

				if (uSession.user.getUserId().equals(userId))

					if (uSession.user.getUserId().equals(userId) && uSession.session.getId() != session.getId()) {
						System.out.println(DateUtils.getTime() + "不发送玩家断线消息" + session.getAttribute("user"));
						return;
					}
			}
		}

		System.out.println(DateUtils.getTime() + "发送玩家断线消息" + session.getAttribute("user"));
		userInfo.setLostConnection(1);

		if (userInfo.getRoomId() != null) {
			IRoomInfo roomInfo = userSessionMap.get(userInfo.getRoomId());
			if (roomInfo != null) {
				synchronized (roomInfo) {// 参考java编程思想 689页
					if (roomInfo.getParticipation() == roomInfo.getActualPrepare()) {// 说明此时已经发牌了
						// 通知所有人他掉线了
						notificationService.notificationLoseConnection(roomInfo.getRoomId(), userId);
					} else {
						// 通知所有人他掉线了,并且将他的准备状态置为0
						if (userInfo.getPrepare() != null && userInfo.getPrepare() == 1) {
							userInfo.setPrepare(0);
							roomInfo.setActualPrepare(roomInfo.getActualParticipation() - 1);
						}
						notificationService.notificationLoseConnection(roomInfo.getRoomId(), userId);
					}
				}
			}
		}

	}

	@Override
	public void sessionCreated(IoSession session) throws Exception {
		System.out.println(DateUtils.getTime() + "用户" + session.getAttribute("user") + "与服务器建立连接");

		// log.debug(String.format("Client[%s]与Server建立连接!",
		// session.getRemoteAddress()));
		// System.out.println("sessionCreated");

		// String clientIP =
		// ((InetSocketAddress)session.getRemoteAddress()).getAddress().getHostAddress();
		// session.setAttribute("KEY_SESSION_CLIENT_IP", clientIP);
	}

	@Override
	public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
		// log.debug(session.getServiceAddress() +"IDS");
		System.out.println(DateUtils.getTime() + "用户" + session.getAttribute("user") + "sessionIdle");
	}

	@Override
	public void sessionOpened(IoSession session) throws Exception {
		// log.debug("连接打开："+session.getLocalAddress());
		System.out.println(DateUtils.getTime() + "用户" + session.getAttribute("user") + "sessionOpened");
	}

	private final int FUNCTIONCODE_RECONNECT = 0;// 断线重连
	private final int FUNCTIONCODE_CREATEROOM = 1;// 创建房间
	private final int FUNCTIONCODE_JOINROOM = 2;// 加入房间
	private final int FUNCTIONCODE_READY = 5;// 准备
	private final int FUNCTIONCODE_SHOWCARD = 12;// 亮牌
	private final int FUNCTIONCODE_SENDMESSAGE = 16;// 发送消息
	private final int FUNCTIONCOD_APPLYDIS = 20;// 申请退房
	private final int FUNCTIONCOD_GETIP = 24;// 获取IP地址
	private final int FUNCTIONCOD_RETURNTOHALL = 25;// 返回大厅
	private final int FUNCTIONCOD_RETURNTOROOM = 27;// 返回游戏房间
	private final int FUNCTIONCOD_DISROOM = 30;// 房主一键解散房间
	private final int FUNCTIONCOD_RECONNECTINGAME = 33;// 游戏中断线重连
	private final int FUNCTIONCOD_GETROOMCARD = 35;// 请求房卡

	// 麻将
	// 自己摸牌时进行
	private final int FUNCTIONCOD_HU_XCMJ = 41;
	// 自摸明杠
	private final int FUNCTIONCOD_ZIMOMINGGANG_XCMJ = 43;
	// 自摸暗杠
	private final int FUNCTIONCOD_ZIMOANGANG_XCMJ = 46;
	// 胡碰杠
	private final int FUNCTIONCOD_HGPQUEUE_XCMJ = 45;
	// 出牌
	private final int FUNCTIONCOD_DISCARD_XCMJ = 44;
	// 过
	private final int FUNCTIONCOD_PASS_XCMJ = 47;
}
